<template>
  <div style="margin-top: 10px; padding-bottom: 20px">
    <el-row>
      <el-col :span="2" style="padding: 0">
        <el-table ref="multipleTable" :data="filteredFields" tooltip-effect="dark" style="width: 100%" height="50vh"
          highlight-current-row class="myDiv" @current-change="handleCurrentChange($event, '0')" :show-header="false">
          <el-table-column prop="fieldTitle" align="center"> </el-table-column>
        </el-table>
      </el-col>
      <el-col :span="17">
        <el-form :model="dynamicValidateForm" ref="dynamicValidateForm" size="mini" style="
            border: 1px solid #ccc;
            margin: 0 0 0 10px;
            padding: 15px 10px 25px;
            min-height: 450px;
          " label-width="100px" class="demo-dynamic">
          <draggable v-model="dynamicValidateForm.domains" animation="500" @start="drag = true" @end="drag = false">
            <div v-for="(domain, index) in dynamicValidateForm.domains" :key="domain.defineId" :class="[
              'el-col',
              'el-col-' + domain.singleFlag,
              { highlighted: domain.defineId === highlightItem.defineId },
            ]" v-show="domain.editFlag == 1" @click="getCurrentRow(domain, '0')">
              <el-form-item :label="domain.fieldTitle" :prop="'domains.' + index + '.defaultVal'" :rules="{
                required: domain.notNullFlag == 1,
                trigger: domain.inputType !== 'checkbox' ? ['blur', 'change'] : null,
                message: `请输入${domain.fieldTitle}`,
              }">
                <el-input v-if="domain.inputType == 'input'" v-model="domain.defaultVal" clearable
                  :disabled="domain.readOnlyFlag == 1" :placeholder="`请输入${domain.fieldTitle}`">
                </el-input>
                <el-select v-else-if="domain.inputType == 'select'" v-model="domain.defaultVal" clearable
                  :placeholder="`请选择${domain.fieldTitle}`" :disabled="domain.readOnlyFlag == 1">
                  <el-option v-for="item in domain.dictItemList" :key="item.dictItemId" :label="item.itemText"
                    :value="item.itemValue">
                  </el-option>
                </el-select>
                <el-checkbox-group v-model="domain.defaultVal" v-else-if="domain.inputType == 'checkbox'">
                  <el-checkbox v-for="item in domain.dictItemList" :key="item.dictItemId" :label="item.itemValue"
                    :disabled="domain.readOnlyFlag == 1">
                    {{ item.itemText }}
                  </el-checkbox>
                </el-checkbox-group>
                <el-radio-group v-model="domain.defaultVal" v-else-if="domain.inputType == 'radio'">
                  <el-radio v-for="item in domain.dictItemList" :key="item.dictItemId" :label="item.itemValue">{{
                    item.itemText }}</el-radio>
                </el-radio-group>
                <el-date-picker v-else-if="domain.inputType == 'date'" v-model="domain.defaultVal" type="date"
                  value-format="YYYY-MM-DD" :placeholder="`请选择${domain.fieldTitle}`"
                  :disabled="domain.readOnlyFlag == 1">
                </el-date-picker>
                <el-date-picker v-else-if="domain.inputType == 'time'" v-model="domain.defaultVal" type="datetime"
                  :placeholder="`请选择${domain.fieldTitle}`" :disabled="domain.readOnlyFlag == 1">
                </el-date-picker>
              </el-form-item>
            </div>
          </draggable>
        </el-form>
      </el-col>
      <el-col :span="5" style="padding-right: 0px">
        <el-form :model="fielsform" ref="fielsform" label-width="100px"
          style="max-height: 450px; overflow: hidden; overflow-y: auto" size="mini">
          <el-form-item label="字段标题">
            <el-input v-model="fielsform.fieldTitle" clearable></el-input>
          </el-form-item>
          <el-form-item label="默认值">
            <el-input v-model="fielsform.defaultVal" placeholder="请输入默认值" clearable></el-input>
          </el-form-item>
          <el-form-item label="控件类型">
            <el-select v-model="fielsform.inputType" clearable placeholder="请选择控件类型" @change="changeFieldType">
              <el-option v-for="item in controlType" :key="item.value" :label="item.label" :value="item.value">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="数据字典" v-show="fielsform.inputType == 'select' ||
            fielsform.inputType == 'radio' ||
            fielsform.inputType == 'checkbox'
            ">
            {{ fielsform.dictCode }}

            <el-popover placement="right" width="600" trigger="click">
              <el-table :data="gridData" height="250" ref="tabledic" @selection-change="handleSelectionChangedic">
                <el-table-column type="selection" width="55"></el-table-column>
                <el-table-column property="dictName" label="字典名称"></el-table-column>
                <el-table-column property="dictCode" label="字典编码"></el-table-column>
                <el-table-column property="description" label="字典描述"></el-table-column>
              </el-table>

              <el-button slot="reference" size="mini" @click="chooseDctionary" type="primary">
                选择字典</el-button>
            </el-popover>
          </el-form-item>
          <el-form-item label="最大长度">
            <el-input v-model="fielsform.maxLength" clearable></el-input>
          </el-form-item>
          <!-- <el-form-item label="是否隐藏">
            <el-checkbox v-model="fielsform.readOnlyFlag"></el-checkbox>
          </el-form-item> -->
          <el-row>
            <el-col :span="12">
              <el-form-item label="是否只读">
                <el-checkbox v-model="fielsform.readOnlyFlag"></el-checkbox> </el-form-item></el-col>
            <el-col :span="12">
              <el-form-item label="复制上一条">
                <el-checkbox v-model="fielsform.copyFlag"></el-checkbox> </el-form-item></el-col>
          </el-row>
          <el-row>
            <el-col :span="12">
              <el-form-item label="是否必填">
                <el-checkbox v-model="fielsform.notNullFlag"></el-checkbox>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="是否打印">
                <el-checkbox v-model="fielsform.printFlag"></el-checkbox>
              </el-form-item>
            </el-col>
          </el-row>

          <el-form-item label="正则表达式" v-if="fielsform.notNullFlag == 1">
            <!-- <el-input v-model="fielsform.verifyRule" clearable placeholder="例如：^[0-9]*$">
            </el-input> -->
            <el-select v-model="fielsform.verifyRule" clearable placeholder="请选择对应的正则表达式">
              <el-option v-for="item in regularLIist" :key="item.value" :label="item.label" :value="item.value">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="验证提示" v-if="fielsform.notNullFlag == 1">
            <el-input v-model="fielsform.verifyMsg" clearable placeholder="请输入校验错误的提示">
            </el-input>
          </el-form-item>
          <el-form-item label="按行展示">
            <el-radio-group v-model="fielsform.singleFlag">
              <el-radio :label="8">一行三列</el-radio>
              <el-radio :label="12">一行两列</el-radio>
              <el-radio :label="24">独占一行</el-radio>
            </el-radio-group>
          </el-form-item>
          <span class="flex">
            <el-tooltip content="上移" placement="bottom" effect="light">
              <el-button size="mini" style="margin-left: 30px" circle icon=" el-icon-top"
                @click="move('up', highlightItem.defineId, fielsform.editFlag)"></el-button>
            </el-tooltip>
            <el-tooltip content="下移" placement="bottom" effect="light">
              <el-button size="mini" circle icon="el-icon-bottom"
                @click="move('down', highlightItem.defineId, fielsform.editFlag)"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="bottom" effect="light">
              <el-button size="mini" type="danger" icon="el-icon-delete" circle
                @click="move('del', highlightItem.defineId, fielsform.editFlag)"></el-button>
            </el-tooltip>
          </span>
          <span class="beCareful_text bottom20">*点击左侧字段生成组件</span>
          <span class="beCareful_text bottom10">*在右侧可编辑组件的属性</span>
        </el-form>
      </el-col>
    </el-row>
    <span slot="footer" class="dialog-footer" style="float: right">
      <el-button type="primary" @click="updateFields" size="mini">确 定</el-button>
    </span>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import { busFieldDefineListLabel, busFieldDefineListBox } from '@/api/sys/field'
import { sysDictPage, updateArchiveFields, updateBoxFields, getDictItems } from '@/api/sys/dict'

import draggable from 'vuedraggable'

export default {
  name: 'CustomFrom',
  components: { draggable },
  props: {
    label: {
      type: String,
      default: '0',
    },
  },
  data() {
    return {
      dragIndex: '',
      drag: false,
      radio: '0',
      fieldslists: [],
      dynamicValidateForm: {
        domains: [],
      },
      innerVisible: false,
      fielsform: {
        singleFlag: '8',
      },
      highlightItem: {},
      uniqueList: [],
      // 控件类型
      controlType: [
        { label: '文本框', value: 'input' },
        { label: '下拉框', value: 'select' },
        { label: '复选框', value: 'checkbox' },
        { label: '单选框', value: 'radio' },
        { label: '日期', value: 'date' },
        { label: '时间', value: 'time' },
      ],

      optionlist: [],
      tableProps: [
        { prop: 'value', checked: true },
        { prop: 'label', checked: true },
      ],
      gridData: [],
      selectedRow: null,
      regularLIist: [],
    }
  },
  computed: {
    ...mapState(['fields']),
    filteredFields() {
      return this.fields.filter((item) => item.fieldType != 0)
    },

    'fielsform.readOnlyFlag': {
      // 当获取checkboxValue的值时，将布尔值转换为字符串
      get() {
        return this.fielsform.readOnlyFlag === 'true'
      },
      // 当更改checkboxValue的值时，更新rawValue的值为字符串
      set(value) {
        this.fielsform.readOnlyFlag = value.toString()
      },
    },
    'fielsform.notNullFlag': {
      // 当获取checkboxValue的值时，将布尔值转换为字符串
      get() {
        return this.fielsform.notNullFlag === 'true'
      },
      // 当更改checkboxValue的值时，更新rawValue的值为字符串
      set(value) {
        this.fielsform.notNullFlag = value.toString()
      },
    },
    'fielsform.printFlag': {
      // 当获取checkboxValue的值时，将布尔值转换为字符串
      get() {
        return this.fielsform.printFlag === 'true'
      },
      // 当更改checkboxValue的值时，更新rawValue的值为字符串
      set(value) {
        this.fielsform.printFlag = value.toString()
      },
    },
  },
  watch: {
    fielsform: {
      deep: true,
      handler(NEWV) {
        // 如果监听到fielsform中的值，就去改变dynamicValidateForm.domains中对应的值
        this.dynamicValidateForm.domains = this.dynamicValidateForm.domains.map((item) =>
          item.defineId === NEWV.defineId ? NEWV : item
        )
      },
    },
  },

  mounted() {
    this.$nextTick(() => {
      const dragBox = document.querySelectorAll('.outputTable .isDragBox')
      dragBox.forEach((i, idx) => {
        i.setAttribute('draggable', 'true')
        i.ondragstart = () => this.dragStartItem(idx)
        i.ondragover = () => this.dragOverItem(idx)
        i.ondragend = () => this.dragEndItem()
      })
    })
    this.loadData()
    this.allUpdateFileds()
    this.getRegularList()
  },

  methods: {
    transferList(e) {
      this.$forceUpdate()
    },
    // 获取正则表达式的字典
    async getRegularList() {
      const res = await getDictItems('regular_expression')
      if (res.data.code == 200) {
        this.regularLIist = res.data.data
      } else {
        this.$message.error(res.data.message)
      }
    },
    // 点击当前的自定义表单的组件，实现选中当前组件
    getCurrentRow(domain, model) {
      // 调用handleCurrentChange方法，传入domain和model参数
      this.handleCurrentChange(domain, model)
    },
    // 全部展示字段
    allUpdateFileds() {
      // 遍历fields数组，调用handleCurrentChange方法，传入item和'1'参数
      this.fields.map((item) => {
        this.handleCurrentChange(item, '1')
      })
    },
    convertEmptyStringsToNullInProperties(obj, properties) {
      properties.forEach((property) => {
        obj[property] = obj[property] === '' ? null : obj[property]
      })
    },
    // 更新字段
    updateFields() {
      var url
      // 将readOnlyFlag根据布尔值转化为数字，但是其他值不变
      // 遍历动态验证表单中的 domains 属性，为每个 item 添加 editSort 属性，并设置 readOnlyFlag 和 notNullFlag 的值
      const params = this.dynamicValidateForm.domains.map((item, index) => {
        // 为每个 item 添加 editSort 属性，editSort 表示 item 在数组中的索引
        item.editSort = index
        const convertBoolToBinary = (flag) => (flag ? 1 : 0)
        // 如果 item 的 readOnlyFlag 为 true，则将其值设置为 1，否则设置为 0
        item.readOnlyFlag = convertBoolToBinary(item.readOnlyFlag)
        // 如果 item 的 notNullFlag 为 true，则将其值设置为 1，否则设置为 0
        item.notNullFlag = convertBoolToBinary(item.notNullFlag)
        // 如果 item 的 printFlag 为 true，则将其值设置为 1，否则设置为 0
        item.printFlag = convertBoolToBinary(item.printFlag)
        // 如果 item 的 copyFlag 为 true，则将其值设置为 0，否则设置为 1
        item.copyFlag = convertBoolToBinary(!item.copyFlag)
        // 调用函数
        // 如果默认值为''，返回null
        const propertiesToConvert = ['defaultVal', 'dictCode', 'verifyRule', 'verifyMsg']
        this.convertEmptyStringsToNullInProperties(item, propertiesToConvert)
        // 返回修改后的 item
        return item
      })

      if (this.label == '1') {
        url = updateBoxFields(params)
      } else {
        url = updateArchiveFields(params)
      }
      url.then((res) => {
        if (res.data.code === 200) {
          this.$message.success(res.data.message)
          this.getbusFieldDefine(this.label)
        } else {
          this.$message.error(res.data.message)
        }
      })
    },
    //获取字段数据
    getbusFieldDefine(label) {
      var url
      if (label == 1) {
        url = busFieldDefineListBox(1)
      } else {
        url = busFieldDefineListLabel(1)
      }
      url
        .then((res) => {
          if (res.data.code == 200) {
            this.dynamicValidateForm.domains = res.data.data

            this.$store.commit('setFiels', res.data.data)
          } else {
            this.$message.error(res.data.message)
          }
        })
        .catch((err) => {
          this.$message.error(err)
        })
    },
    loadData() {
      sysDictPage({ pageSize: 99, pageNo: 1 })
        .then((res) => {
          if (res.data.code === 200) {
            this.gridData = res.data.data.records
          } else {
            this.$message.error(res.data.message)
          }
        })
        .catch((err) => {
          this.$message.error(err)
        })
    },
    handleSelectionChangedic(val) {
      // 处理字典表单的选中记录
      if (val.length > 1) {
        // 如果选中的记录大于1条，清空选择
        this.$refs.tabledic.clearSelection()
        // 选中最后一条记录
        this.$refs.tabledic.toggleRowSelection(val[val.length - 1])
        // 更新字典编码
        this.fielsform.dictCode = val[val.length - 1].dictCode
      } else if (val.length == 0) {
        // 如果选中的记录为0条，清空字典编码
        this.fielsform.dictCode = ''
      } else if (val.length == 1) {
        // 如果选中的记录为1条，更新字典编码
        this.fielsform.dictCode = val[0].dictCode
        setTimeout(() => {
          this.updateFields()
        }, 500)
      }
    },
    chooseDctionary() {
      // 根据字典编码在表格中选择一行
      const row = this.gridData.find((item) => item.dictCode === this.fielsform.dictCode)
      if (row) {
        // 如果找到记录，选中一行
        this.$refs.tabledic.toggleRowSelection(row, true)
      }
    },
    // 选择字典
    // choicedDctionary() {},
    // 表格输入框的触发的方法
    inputValue() {
      // 修改值的时候，重新将表单数据更新
      const updatedDomains = this.dynamicValidateForm.domains.map((item) => {
        if (item.defineId == this.fielsform.defineId) {
          item.option = this.fielsform.option
        }
        return item
      })
      this.dynamicValidateForm.domains = updatedDomains
    },
    // 下拉框更改值得时候
    changeFieldType() {
      // 下拉框选择的时候，重新将表单数据更新
      const updatedDomains = this.dynamicValidateForm.domains.map((item) => {
        // 如果下拉框的id和当前表单的id相同
        if (item.defineId == this.fielsform.defineId) {
          // 更新表单的类型
          item.inputType = this.fielsform.inputType
        }
        return item
      })
      // 清空默认值
      this.fielsform.defaultVal = null
      // 更新下拉框的数据
      this.dynamicValidateForm.domains = updatedDomains
    },

    // 开始拖拽时，记录被拖拽的项的索引
    dragStartItem(idx) {
      this.dragIndex = idx
    },
    // 拖拽过程中，记录新的拖拽索引
    dragOverItem(index) {
      this.newDragIndex = index
    },
    // 结束拖拽时，将被拖拽的项插入到新的拖拽索引位置
    dragEndItem() {
      const data = this.optionlist[this.dragIndex]
      this.optionlist.splice(this.dragIndex, 1)
      this.optionlist.splice(this.newDragIndex, 0, data)
    },
    activeClass({ row, rowIndex }) {
      if (rowIndex === this.newDragIndex) {
        return 'isDragBox active-drag'
      }
      return 'isDragBox'
    },
    // 增加表格行
    AddTableRow() {
      // 获取当前 table_data 中最大的 id。
      let id = this.fielsform.option.map((object) => object.id)
      const max_id = Math.max(...id)
      // 获取最后一个对象。
      const lastObject = this.fielsform.option[this.fielsform.option.length - 1]
      // 创建一个新的空对象。
      var addObj = {}
      // 遍历 table_data 中的对象，并为新对象添加与之对应的键。
      for (const key in lastObject) {
        addObj[key] = lastObject[key]
      }
      // 将新对象的 id 设置为当前最大 id 加 1。
      addObj = {
        label: 'new option',
        value: max_id + 1,
        id: max_id + 1,
      }
      this.fielsform.option.push(addObj)
      // this.isUpdate = !this.isUpdate;//重新渲染表格 不能和下面的代码同时使用
      this.$nextTick(() => {
        this.$refs.addTableRowRef.bodyWrapper.scrollTop =
          this.$refs.addTableRowRef.bodyWrapper.scrollHeight
      })
      this.inputValue()
    },
    submit() { },
    handleSelectionChange(item) { },
    pushdoMains(flag, item, inputType) {
      if (!flag) {
        // 不存在
        const pushItme = {
          defineId: item.defineId,
          fieldName: item.fieldName,
          fieldTitle: item.fieldTitle,
          inputType: item.inputType || 'input',
          placeholder: item.placeholder,
          defaultVal: item.defaultVal,
          dictCode: item.dictCode,
          readOnlyFlag: item.readOnlyFlag == 1,
          editFlag: item.editFlag,
          editSort: item.editSort,
          maxLength: item.maxLength,
          singleFlag: item.singleFlag,
          notNullFlag: item.notNullFlag == 1,
          verifyRule: item.verifyRule,
          verifyMsg: item.verifyMsg,
          dictItemList: item.dictItemList,
          copyFlag: item.copyFlag == 0,
          printFlag: item.printFlag == 1,
        }
        this.fielsform = pushItme
        this.dynamicValidateForm.domains.push(pushItme)
        this.highlightItem = item //高亮判断
      } else {
        // 使用this.dynamicValidateForm.domains的值
        this.fielsform = this.dynamicValidateForm.domains.filter(
          (x) => x.defineId === item.defineId
        )[0]

        this.highlightItem = item //高亮判断
      }
    },
    handleCurrentChange(item, mode) {
      // mode代表的是点击方式
      // 1代表的是自动循环，不需要鼠标点击事件
      // 0代表的是手动点击 即鼠标点击

      // 判断这个组件是否在动态表单中
      // 如果有的话，就将这个组件的值赋给动态表单的值
      // 如果没有的话，就使用item的值，给动态表单
      // 判断item是否已经存在于domains数组中
      let flag = this.dynamicValidateForm.domains.some((x) => x.defineId === item.defineId)
      // 获取item的fieldType
      let inputType = this.dynamicValidateForm.domains.find(
        (obj) => obj.defineId === item.defineId
      )?.fieldType
      if (mode == '1') {
        // 如果是添加模式，判断item是否可以编辑
        if (item.editFlag == '1') {
          // 调用添加方法
          this.pushdoMains(flag, item, inputType)
        }
      } else {
        // 如果是鼠标点击，将item的编辑状态改为1
        // 调用添加方法
        item.editFlag = 1
        this.pushdoMains(flag, item, inputType)
      }
    },
    // 表单item移动的逻辑
    move(flag, key, editFlag) {
      // 获取要移动的数组元素的索引
      let index = this.dynamicValidateForm.domains.findIndex((item) => item.defineId === key)
      if (flag == 'up') {
        // 如果是向上移动，则与上边一个元素交换位置
        if (index > 0) {
          const temp = this.dynamicValidateForm.domains[index]
          this.dynamicValidateForm.domains[index] = this.dynamicValidateForm.domains[index - 1]
          this.dynamicValidateForm.domains[index - 1] = temp
        }
      } else if (flag == 'down') {
        // 如果是向下移动，则与下边一个元素交换位置
        if (index < this.dynamicValidateForm.domains.length - 1) {
          const temp = this.dynamicValidateForm.domains[index]
          this.dynamicValidateForm.domains[index] = this.dynamicValidateForm.domains[index + 1]
          this.dynamicValidateForm.domains[index + 1] = temp
        }
      } else if (flag == 'del') {
        //
        /**
         * 如果是删除元素，则直接从数组中移除
         * 不能删除数组，否则不能得后端传数据，改不了值,只能通过改变editFlag的状态来控制组件的显示与否，
         * 这样可以即改变状态又能可以向后端传数据
         */
        // 将对应的这个改为editFlag改为0
        this.dynamicValidateForm.domains[index].editFlag = 0
        this.updateFields()
      }
      // 强制更新界面
      this.$forceUpdate()
    },
  },
}
</script>

<style lang="less" scoped>
.myDiv {
  .el-table .cell {
    padding: 0;
  }
}

.demo-dynamic {
  .el-form-item {
    margin-bottom: 0;
    padding: 5px 10px;
  }
}

.bottom10,
.bottom20 {
  position: absolute;
}

.bottom10 {
  bottom: 10px;
}

.bottom20 {
  bottom: 25px;
}

.highlighted {
  background-color: rgb(235, 234, 234);
}

.el-col-2 {
  margin: 0;
}

.optionlist {
  .el-table td {
    border-bottom: none !important;
  }
}

.isDragBox {
  cursor: move;
  position: relative;
}

.active-drag {
  position: relative;

  &::after {
    content: '';
    position: absolute;
    top: -1px;
    left: 0;
    width: 100%;
    height: 2px;
    background-color: #4b79f3;
    z-index: 99;
  }
}

/* 限制标签宽度 */
.el-form-item__label {
  max-width: 100px;
  /* 根据需要调整这个值 */
  white-space: nowrap;
  /* 防止标签自动换行 */
  overflow: hidden;
  /* 超出部分隐藏 */
  // text-overflow: ellipsis; /* 超出部分显示省略号 */
}

.el-date-editor.el-input {
  width: 100%;
}

.el-form-item {
  margin: 0 10px 0 0;
}

.el-radio {
  margin: 3px 0;
}
</style>
